package Controller

import (
	"backend/Dao"
	"backend/Service/dbService"
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"net/http"
	"sort"
	"strconv"
)

type CurriculumController struct {
}

type newCurriculum struct {
	CurriculumYear     string `json:"CurriculumYear"`
	CurriculumSeriesId int    `json:"CurriculumSeriesId,string"`
	CurriculumData     string `json:"CurriculumData"`
}

//
// SetNewCurriculum
// @Description: 新建课程不许创建同一年份
// @author MaTaoXun 2022-01-15 16:51:29
// @return gin.HandlerFunc
//
func (this CurriculumController) SetNewCurriculum(c *gin.Context) {
	var data = newCurriculum{}
	err := c.BindJSON(&data)
	if err != nil {
		fmt.Println("err", err)
	}
	fmt.Println(data)
	var ifExist Dao.Curriculum
	if err := dbService.DbConn.Where("curriculum_year = ? and curriculum_series_id = ?", data.CurriculumYear, data.CurriculumSeriesId).First(&ifExist); err.Error == gorm.ErrRecordNotFound {
		dbService.DbConn.Create(&Dao.Curriculum{
			Model:              Dao.GetModel(),
			CurriculumYear:     data.CurriculumYear,
			CurriculumSeriesId: data.CurriculumSeriesId,
			CurriculumData:     data.CurriculumData,
		})
		c.String(200, "新建成功")
	} else {
		c.String(200, "出现重复")
	}
}

type getCurriculumsBySeriesId struct {
	SeriesId uint `json:"series_id,string"`
}
type resgetCurriculumsBySeriesId struct {
	ChapterList []Dao.Chapter
	Curriculum  Dao.Curriculum
}

//
// GetCurriculumsBySeriesId
// @Description: 通过课程列表id获取课程
// @author MaTaoXun 2022-01-15 16:52:01
// @return gin.HandlerFunc
//
func (this CurriculumController) GetCurriculumsBySeriesId(c *gin.Context) {
	var data = getCurriculumsBySeriesId{}
	err := c.BindJSON(&data)
	if err != nil {
		fmt.Println("err", err)
	}
	// 课程系列下所有的课程
	getData := &[]Dao.Curriculum{}
	dbService.DbConn.Where("curriculum_series_id = ?", data.SeriesId).Find(getData)

	//rs := make([]resgetCurriculumsBySeriesId, 0)
	currIds := make([]string, 0)
	rsMap := make(map[int]*resgetCurriculumsBySeriesId)
	for _, v := range *getData {
		currIds = append(currIds, strconv.Itoa(int(v.ID)))
		rsMap[int(v.ID)] = &resgetCurriculumsBySeriesId{
			ChapterList: make([]Dao.Chapter, 0),
			Curriculum:  v,
		}
		//c2 := &[]Dao.Chapter{}
		//dbService.DbConn.Where("curriculum_id = ?", v.ID).Order("chapter_sort").Find(c2)
		//rs = append(rs, resgetCurriculumsBySeriesId{
		//	ChapterList: *c2,
		//	Curriculum:  v,
		//})
	}
	chapters := make([]Dao.Chapter, 0)
	dbService.DbConn.Model(&Dao.Chapter{}).Where("curriculum_id in ?", currIds).Select("id", "chapter_name", "chapter_sort", "chapter_describe", "chapter_data", "curriculum_id").Order("chapter_sort").Find(&chapters)
	for _, chapter := range chapters {
		(*rsMap[chapter.CurriculumId]).ChapterList = append((*rsMap[chapter.CurriculumId]).ChapterList, chapter)
	}
	rs := make([]*resgetCurriculumsBySeriesId, 0, len(rsMap))
	for _, v := range rsMap {
		rs = append(rs, v)
	}
	sort.Slice(rs, func(i, j int) bool {
		return rs[i].Curriculum.CurriculumYear > rs[j].Curriculum.CurriculumYear
	})

	c.JSON(200, rs)
}

//
// GetOnlyCurriculumsBySeriesId
// @Description: 获取当前学生有权限的课程
// @author MaTaoXun 2022-01-15 16:52:44
// @return gin.HandlerFunc
//
func (this CurriculumController) GetOnlyCurriculumsBySeriesId(c *gin.Context) {
	stuId, _ := c.Get("userId")
	var data = getCurriculumsBySeriesId{}
	err := c.BindJSON(&data)
	if err != nil {
		fmt.Println("err", err)
	}
	var StudentCurriculums []Dao.StudentCurriculum
	dbService.DbConn.Where("stu_id = ?", stuId).Select("curriculum_id").Find(&StudentCurriculums)
	var currIds []int
	for _, curriculum := range StudentCurriculums {
		currIds = append(currIds, curriculum.CurriculumId)
	}

	getData := &[]Dao.Curriculum{}
	dbService.DbConn.Where("curriculum_series_id = ? and id in ?", data.SeriesId, currIds).Find(getData)

	c.JSON(200, getData)
}

type reqUpdateCurriculumData struct {
	ID          uint   `json:"id,string"`
	ChapterData string `json:"chapter_data"`
}

//
// UpdateCurriculumData
// @Description: 根据课程id更新课程
// @author MaTaoXun 2022-01-15 16:53:25
// @return gin.HandlerFunc
//
func (this CurriculumController) UpdateCurriculumData(c *gin.Context) {
	var data = reqUpdateCurriculumData{}
	err := c.BindJSON(&data)
	curriculum := Dao.Curriculum{
		Model: Dao.Model{
			ID: data.ID,
		},
	}
	dbService.DbConn.Model(&curriculum).Update("curriculum_data", data.ChapterData)
	if err != nil {
		fmt.Println("err", err)
	}
	c.JSON(200, "ok")
}

// ListCurriculum
// @Summary 获取所有课程系列下的所有课程
// @Description 获取所有课程系列下的所有课程
// @Tags 课程相关接口
// @Accept application/json
// @Produce application/json
// @Param tk header string false "token"
// @Success 200 body _resListCurriculum
// @Router /ListCurriculum [get]
func (this CurriculumController) ListCurriculum(c *gin.Context) {
	curriculumSeries := []Dao.CurriculumSeries{}
	dbService.DbConn.Find(&curriculumSeries)
	rs := make([]_resListCurriculum, 0)
	for _, series := range curriculumSeries {
		curriculumList := []Dao.Curriculum{}
		curricula := make([]resListCurriculumCurriculum, 0)
		dbService.DbConn.Where("curriculum_series_id = ?", series.ID).Find(&curriculumList)
		for _, curriculum := range curriculumList {
			curricula = append(curricula, resListCurriculumCurriculum{
				ID:             curriculum.ID,
				CurriculumYear: curriculum.CurriculumYear,
			})
		}
		rs = append(rs, _resListCurriculum{
			ID:                    series.ID,
			CurriculumSeriesName:  series.CurriculumSeriesName,
			CurriculumSeriesValue: series.ID,
			CurriculumList:        curricula,
		})
	}

	c.JSON(200, rs)
}

type resListCurriculumCurriculum struct {
	ID             uint   `json:"value,string"`
	CurriculumYear string `json:"label"`
}
type _resListCurriculum struct {
	ID                    uint                          `json:"ID,string"`
	CurriculumSeriesName  string                        `json:"label"`
	CurriculumSeriesValue uint                          `json:"value,omitempty,string"`
	CurriculumList        []resListCurriculumCurriculum `json:"children"`
}

//
// DeleteCurriculum
// @Description: 删除课程以及其下的章节,作业和作业文件
// @author MaTaoXun 2022-01-15 16:55:30
// @return gin.HandlerFunc
//
func (this CurriculumController) DeleteCurriculum(c *gin.Context) {
	currId := c.Query("id")
	currIdInt, _ := strconv.Atoi(currId)
	curriculum := Dao.Curriculum{Model: Dao.Model{ID: uint(currIdInt)}}
	dbService.DbConn.Delete(&curriculum)
	//删除chapter
	dbService.DbConn.Where("curriculum_id = ?", curriculum.ID).Delete(&Dao.Chapter{})
	var HomeWorkList []Dao.Homework
	dbService.DbConn.Where("curriculum_id = ?", curriculum.ID).Find(&HomeWorkList)
	dbService.DbConn.Where("curriculum_id = ?", curriculum.ID).Delete(&Dao.Homework{})
	//根据HomeWorkid删除homeWorkfile
	for _, homework := range HomeWorkList {
		dbService.DbConn.Where("homework_id = ?", homework.ID).Delete(&Dao.HomeworkFile{})
	}
	c.String(200, "delSuc")
}

type reqChangeCurriculumsStu struct {
	CurriculumId int      `json:"curriculumId,string"`
	StuList      []string `json:"stuList"`
}

//
// ChangeCurriculumsStu
// @Description: 改变课程绑定的学生
// @author MaTaoXun 2022-01-15 16:57:34
// @return gin.HandlerFunc
//
func (this CurriculumController) ChangeCurriculumsStu(c *gin.Context) {
	data := reqChangeCurriculumsStu{}
	c.BindJSON(&data)
	var stuCurrss []Dao.StudentCurriculum
	oldStuSet := make(map[int]struct{})
	newStuSet := make(map[int]struct{})
	delStuList := make([]string, 0)
	addStuList := make([]Dao.StudentCurriculum, 0)
	dbService.DbConn.Where(Dao.StudentCurriculum{CurriculumId: data.CurriculumId}).Select("stu_id").Find(&stuCurrss)
	for _, v := range stuCurrss {
		oldStuSet[v.StuId] = struct{}{}
	}
	for _, v := range data.StuList {
		atoi, _ := strconv.Atoi(v)
		newStuSet[atoi] = struct{}{}
	}
	for _, v := range stuCurrss {
		if _, ok := newStuSet[v.StuId]; !ok {
			delStuList = append(delStuList, strconv.Itoa(v.StuId))
		}
	}
	for _, v := range data.StuList {
		atoi, _ := strconv.Atoi(v)
		if _, ok := oldStuSet[atoi]; !ok {

			addStuList = append(addStuList, Dao.StudentCurriculum{
				Model:        Dao.GetModel(),
				CurriculumId: data.CurriculumId,
				StuId:        atoi,
			})
		}
	}
	dbService.DbConn.Where("curriculum_id = ? and stu_id in ? ", data.CurriculumId, delStuList).Where("").Delete(&Dao.StudentCurriculum{})
	dbService.DbConn.Create(&addStuList)
}

//
// GetCurrStuListByClasss
// @Description: 获取该班级和课程绑定的学生列表
// @author MaTaoXun 2022-01-18 17:16:15
// @return gin.HandlerFunc
//
func (this CurriculumController) GetCurrStuListByClass(c *gin.Context) {
	query := c.Query("classId")
	curriculumId := c.Query("curriculumId")
	var students []Dao.Student
	dbService.DbConn.Where(&Dao.Student{StuClass: query}).Find(&students)
	var stuHomeWorks []Dao.StudentCurriculum
	dbService.DbConn.Where("curriculum_id = ?", curriculumId).Find(&stuHomeWorks)
	stuSet := make(map[int]struct{})
	for _, v := range stuHomeWorks {
		stuSet[v.StuId] = struct{}{}
	}
	var rs struct {
		StuInfo   []Dao.Student
		CheckList []int
	}
	for i := 0; i < len(students); i++ {
		_, ok := stuSet[int(students[i].Model.ID)]
		if ok {
			rs.CheckList = append(rs.CheckList, i)
		}
	}
	rs.StuInfo = students
	c.JSON(http.StatusOK, rs)
}

func (this CurriculumController) GetStuCurrInfo(c *gin.Context) {

	var studentList []StuInfo
	dbService.DbConn.Model(&Dao.Student{}).Find(&studentList)

	var chooseStuList []struct {
		StuId int
	}
	dbService.DbConn.Model(&Dao.StudentCurriculum{}).Where("curriculum_id = ?", c.Query("currId")).Find(&chooseStuList)
	chooseedMap := make(map[int]struct{})
	for _, s := range chooseStuList {
		chooseedMap[s.StuId] = struct{}{}
	}

	var stuList []StuListItem
	for _, info := range studentList {
		if _, exist := chooseedMap[info.Id]; exist {
			stuList = append(stuList, StuListItem{
				StuInfo: info,
				IfCheck: true,
			})
		} else {
			stuList = append(stuList, StuListItem{
				StuInfo: info,
				IfCheck: false,
			})
		}
	}

	rsMap := make(map[string][]StuListItem)
	for _, listItem := range stuList {
		list, exist := rsMap[listItem.StuInfo.StuClass]
		if exist {
			rsMap[listItem.StuInfo.StuClass] = append(list, listItem)
		} else {
			rsMap[listItem.StuInfo.StuClass] = append(make([]StuListItem, 0), listItem)
		}
	}

	var rsStruct []StuhmwElement
	for s, items := range rsMap {
		rsStruct = append(rsStruct, StuhmwElement{
			ClassID: s,
			StuList: items,
		})
	}
	c.JSON(200, rsStruct)
}
